import re
from collections import defaultdict


class HookDispatcher:

    def __init__(self, hooks=None):
        if hooks is not None:
            self.__hooks = self._classify(hooks)
        else:
            self.__hooks = defaultdict(list)

    @staticmethod
    def _classify(hooks):
        mapping = defaultdict(list)

        for hook in hooks:
            for base in hook.__class__.__bases__:
                mapping[base].append(hook)

        return mapping

    def run(self, cls, container):
        if cls in self.__hooks:
            method_name = self._get_method_name(cls)
            for hook in self.__hooks[cls]:
                method = getattr(hook, method_name)
                method(container)

    @staticmethod
    def _get_method_name(cls):
        cls_name = cls.__name__[:-4]
        cls_name = re.sub(r"[a-z][A-Z]", lambda x: x.group(0)[0] + " " + x.group(0)[1], cls_name)
        parts = cls_name.split()
        parts = [part.lower() for part in parts]

        return "_".join(parts)
